import { _decorator, Component, Enum, Node, UITransform } from 'cc';
import { DEV } from 'cc/env';
import { DIR } from '../../../tools/Define';
const { ccclass, property } = _decorator;
export enum NeighborType {
    POS_DEL_XY,//移动时排除XY方向上的内容
    POS_DEL_X,//上下移动时排除X方向上的内容
    POS_DEL_Y,//左右移动时排除Y方向上的内容
    POS,//移动时不排除XY方向上的内容
    CUSTOM,//自定义邻居节点
}

@ccclass('NeighborHandler')
export class NeighborHandler extends Component {

    protected _neighborType = NeighborType.POS_DEL_XY;

    @property({ type: Enum(NeighborType) })
    set neighborType(value: NeighborType) {
        this._neighborType = value;
        switch (this._neighborType) {
            case NeighborType.CUSTOM:
                this.neighborNodes.length = 4;
                break;
            default:
                this.neighborNodes.length = 0;
                break;
        }
    }

    get neighborType() {
        return this._neighborType;
    }

    @property({ tooltip: DEV && "左0 右1 上2 下3 " })
    @property([Node])
    neighborNodes: Node[] = [];//相邻节点，位于LayoutViewHelper容器时才需要设置


    // @property({ tooltip: DEV && "上下移动时是否排除左右方向上的内容" })
    // @property
    // dirX: boolean = true;

    // @property({ tooltip: DEV && "左右移动时是否排除Y方向上的内容" })
    // @property
    // dirY: boolean = true;

    @property({ tooltip: DEV && "是否使用最短路径" })
    @property
    isNearest: boolean = true;


    getNext(dir: DIR, itemList?: Component[]): Node {
        if (!itemList || itemList.length == 0) {
            return null;
        }
        switch (this.neighborType) {
            case NeighborType.CUSTOM:
                return this.neighborNodes[dir]
            default:
                let index = this.getItemByDir(this, dir, itemList)
                if (index >= 0 && index <= itemList.length - 1) {
                    return itemList[index].node
                }
                break;
        }
        return null;
    }

    private getList(clickItem: Component, dir: DIR, itemList: Component[]) {
        let swp = clickItem.node.worldPosition;
        let sMidx = swp.x;
        let sMidy = swp.y;
        let sTransform = clickItem.node.getComponent(UITransform);
        //宽度的一半
        let swh = sTransform.width / 2;
        // LogUtils.log(' swh ', swh)
        // let shh = sTransform.height / 2;
        let list: { index: number, disx: number, disy: number }[] = []
        let items = itemList;
        for (let index = 0; index < items.length; index++) {
            const element = items[index];
            if (element != clickItem && element.node.active && element.node.activeInHierarchy) {
                let tTransform = element.node.getComponent(UITransform);
                //宽度的一半
                let twh = tTransform.width / 2;
                //选择一个比较大的宽度
                let bw = twh > swh ? twh : swh;

                let wpos = element.node.worldPosition;
                //这个地方默认锚点都是0.5,0.5，没有考虑锚点是其他情况。
                let tMidx: number = wpos.x;
                let tMidy: number = wpos.y;
                let disx: number = Math.abs(tMidx - sMidx);
                let disy: number = Math.abs(tMidy - sMidy)
                let flag = false;
                switch (this.neighborType) {
                    case NeighborType.POS_DEL_XY:
                        switch (dir) {
                            case DIR.RIGHT://向右移动时
                                if (tMidx > sMidx && disx > bw) {
                                    flag = true;
                                }
                                break;
                            case DIR.LEFT:
                                if (tMidx < sMidx && disx > bw) {
                                    flag = true;
                                }
                                break;
                            case DIR.UP:
                                if (tMidy > sMidy && disx < bw) {
                                    flag = true;
                                }
                                break;
                            case DIR.DOWN:
                                if (tMidy < sMidy && disx < bw) {
                                    flag = true;
                                }
                                break;
                        }
                        break;
                    case NeighborType.POS_DEL_X:
                        switch (dir) {
                            case DIR.RIGHT://向右移动时
                                if (tMidx > sMidx) {
                                    flag = true;
                                }
                                break;
                            case DIR.LEFT:
                                if (tMidx < sMidx) {
                                    flag = true;
                                }
                                break;
                            case DIR.UP:
                                if (tMidy > sMidy && disx < bw) {
                                    flag = true;
                                }
                                break;
                            case DIR.DOWN:
                                if (tMidy < sMidy && disx < bw) {
                                    flag = true;
                                }
                                break;
                        }
                        break;
                    case NeighborType.POS_DEL_Y:
                        switch (dir) {
                            case DIR.RIGHT://向右移动时
                                if (tMidx > sMidx && disx > bw) {
                                    flag = true;
                                }
                                break;
                            case DIR.LEFT:
                                if (tMidx < sMidx && disx > bw) {
                                    flag = true;
                                }
                                break;
                            case DIR.UP:
                                if (tMidy > sMidy) {
                                    flag = true;
                                }
                                break;
                            case DIR.DOWN:
                                if (tMidy < sMidy) {
                                    flag = true;
                                }
                                break;
                        }
                        break;
                    case NeighborType.POS:
                        switch (dir) {
                            case DIR.RIGHT://向右移动时

                                if (tMidx > sMidx) {
                                    flag = true;
                                }


                                break;
                            case DIR.LEFT:
                                if (tMidx < sMidx) {
                                    flag = true;
                                }
                                break;
                            case DIR.UP:
                                if (tMidy > sMidy) {
                                    flag = true;
                                }
                                break;
                            case DIR.DOWN:
                                if (tMidy < sMidy) {
                                    flag = true;
                                }
                                break;
                        }
                        break;
                }
                if (flag) {
                    let obj = { index: index, disx: disx, disy: disy }
                    list.push(obj)
                }

            }
        }
        return list;
    }

    private getItemByDir(clickItem: Component, dir: DIR, itemList: Component[]): number {
        let list = this.getList(clickItem, dir, itemList)
        this.sortList(list, dir)
        // LogUtils.warn('list ', list)
        if (list.length > 0) {
            let obj = list[0]
            // return this.itemViews[obj.index].node
            return obj.index;
        } else {
            return -1;
        }

    }

    private sortList(list: { index: number, disx: number, disy: number }[], dir: DIR) {
        if (this.isNearest) {
            list.sort((b, a) => {
                return (b.disy * b.disy + b.disx * b.disx) - (a.disy * a.disy + a.disx * a.disx);
            })
        } else {
            switch (dir) {
                case DIR.LEFT:
                case DIR.RIGHT:
                    list.sort((b, a) => {
                        return b.disx - a.disx;
                    })
                    break;
                case DIR.UP:
                case DIR.DOWN:
                    list.sort((b, a) => {
                        return b.disy - a.disy;
                    })
                    break;
            }
        }
    }
}


